ewx-public Package
The ewx-public package provides the public API for writing custom rules on the Energyworx platform. By installing this package locally, you get type hints, IDE autocompletion, and the ability to develop and test rules outside the platform.
For installation, see the ewx-public package page. For local development setup (writing rules, unit-testing locally, uploading to the platform), see Local Rule Development.
Pin ewx-public to the version that matches the platform release you target — for platform release YY.MM the package version is YY.M.0 (e.g. platform 26.03 ships ewx-public==26.3.0). See Versioning for details.
Migrating from the Legacy Packages
ewx-public replaces the older energyworx_public and energyworx packages that were previously used for rule development. The main changes are:
| Legacy import | New import (ewx-public) |
|---|---|
from energyworx.rules.base_rule import AbstractRule | from ewx_public.flow_rule import FlowRule |
from energyworx_public.rule import AbstractTransformRule | from ewx_public.transform_rule import TransformRule |
from energyworx_public.domain import FlowCancelException | from ewx_public import FlowCancelException |
from energyworx_public.domain import FlowStopException | from ewx_public import FlowStopException |
The legacy imports (energyworx_public and energyworx) continue to work on the platform. You do not need to update existing rules. However, for new rules we recommend using ewx-public as it provides better type hints and IDE support.
What's Included
The package provides the base classes and models needed to write custom rules:
| Class | Import | Purpose |
|---|---|---|
FlowRule | from ewx_public.flow_rule import FlowRule | Base class for flow rules (replaces AbstractRule) |
TransformRule | from ewx_public.transform_rule import TransformRule | Base class for transform rules (replaces AbstractTransformRule) |
RuleResult | from ewx_public import RuleResult | Required return type for flow rule apply methods |
FlowCancelException | from ewx_public import FlowCancelException | Cancel a flow execution |
FlowStopException | from ewx_public import FlowStopException | Stop a flow execution |
Domain models such as Datasource, Channel, Tag, TimesliceGroup, FlowConfiguration, and ChannelClassifier are also available under ewx_public.domain.models.
For details on rule structure, available methods, and design patterns, see the other pages in this section.
Testing Module (ewx_public.testing)
The ewx_public.testing subpackage is available from platform release 26.05 onwards (package version ewx-public==26.5.0). Pin to that version or later to use the testing utilities described below.
The ewx_public.testing subpackage provides everything needed to unit-test custom rules locally, without the Energyworx platform. A single pip install ewx-public includes both the rule base classes and the testing utilities.
from ewx_public.testing import make_testable, make_datasource, make_timeseries_df
from ewx_public.testing import assert_timeseries_stored
Core API
| Function / Class | Import | Purpose |
|---|---|---|
make_testable(RuleClass, ...) | from ewx_public.testing import make_testable | Wrap any FlowRule subclass for local testing |
TestableFlowRule | from ewx_public.testing import TestableFlowRule | The concrete FlowRule used under the hood by make_testable |
Factory Functions
Create test objects with sensible defaults — all keyword-only with auto-incrementing IDs:
| Function | Creates |
|---|---|
make_datasource(id=, channels=, tags=, timezone=) | Datasource |
make_channel(name=, classifier=) | Channel |
make_tag(tag=, properties=) | Tag (includes a default property) |
make_tag_property(key=, value=) | TagProperty |
make_timeseries_df(columns=, start=, periods=, freq=, timezone=) | pd.DataFrame with DatetimeIndex |
make_namespace(id=, name=) | Namespace (for rules accessing self.namespace) |
make_flow_configuration(id=, name=) | FlowConfiguration |
make_channel_classifier(name=) | ChannelClassifier |
make_timeslice_group(name=) | TimesliceGroup |
reset_factory_counters() | Resets auto-incrementing IDs for deterministic tests |
Assertion Helpers
Check rule side effects with descriptive error messages. The count parameter: None = at least one, 0 = none, integer = exact count.
| Function | Checks |
|---|---|
assert_timeseries_stored(rule, channel_id=, datasource_id=, count=) | store_timeseries() calls |
assert_annotations_stored(rule, channel_id=, count=) | store_annotations() calls |
assert_tags_added(rule, datasource_id=, tag_name=, count=) | add_tags() calls |
assert_trigger_sent(rule, trigger_type=, count=) | trigger_flow() / publish_to_custom_pubsub_topic() calls |
assert_email_sent(rule, to_email=, subject_contains=, count=) | send_email() calls |
assert_task_created(rule, title_contains=, count=) | create_task() calls |
assert_counter_value(rule, counter_name, expected_value) | Counter values |
assert_logged(rule, level=, message_contains=, count=) | Log messages |
Stubs and Utilities
| Class / Function | Purpose |
|---|---|
InMemoryBackend | Stores all rule side effects in plain dicts/lists. Accessible via rule.backend. |
CapturingLogger | Default logger — records messages for assertion via .infos, .warnings, .errors |
InMemoryTimeseriesService | Backs self.timeseries_service — seed data with rule.backend.add_timeseries() |
InMemoryDatasourceService | Backs self.datasource_service — seed with rule.backend.add_datasource() |
NullObject | Default for self.services / self.trigger_service — absorbs any attribute access |
raising(exc_type, message) | Returns a callable that raises the given exception when called |
For a complete guide with examples, see Unit Testing Rules: A Practical Guide.